<html>
<script>
/*
先排除为0的特殊情况。然后先看前16位是否全0，如果全0，增加计数，并把这个数左移16位删除已经计数的16个0。然后看前8位是否全0。一直到只剩一位时可以直接计算。整个过程的核心是二分思想。

统计末尾0的个数时思想类似，只是变成了统计后面16位、8位等是否全0。


负数同样以二进制码存储，但使用的是二进制补码（其实正数也是用补码表示）。计算一个数值的二进制补码，需要经过下列三个步骤：

求这个数值绝对值的二进制码
求二进制反码，即将0替换为1，将1替换为0
得到的二进制反码加1

左移符号由两个小于号（<<）表示，这个操作符会将数值的所有位向左移动指定的位数。在左移后，原数值右侧空出的位由0填补。

左移一位其实就相当于将原数值乘以2，左移不会影响操作数的符号位。

右移操作符由两个大于号（>>）表示，这个操作符会将数值向右移动，但保留符号位。在移位过程中，空缺位出现在原数值的左侧，符号位的右侧，用符号位的值来填充空位。右移一位相当于原数除2后向下取整。

无符号右移操作符由三个大于号（>>>）表示，这个操作符会将数值的所有32位都向右移动。对正数来说，无符号右移的结果和有符号相同，但是对负数来说就不一样了，无符号右移会把负数的符号位也进行移动，左边空出位置用0填充。

新的掩码可以在以上掩码上使用逻辑运算创建。例如，掩码 1011 可以通过 FLAG_A、FLAG_B 和 FLAG_D 逻辑或得到：

var mask = FLAG_A | FLAG_B | FLAG_D; // 0001 | 0010 | 1000 => 1011
某个特定的位可以通过与掩码做逻辑与运算得到，通过与掩码的与运算可以去掉无关的位，得到特定的位。例如，掩码 0100 可以用来检查标志位 C 是否被置位：（核心就是判断某位上的数 参考常用位运算整理 下同）

*/
function countLeading0(x) {
  if (!x) 
  	return 32;
  var n = 1;
  if ((x >>> 16) == 0) {
  	n += 16;
  	x <<= 16;
  }
  if ((x >>> 24) == 0) {
  	n += 8;
  	x <<= 8;
  }
  if ((x >>> 28) == 0) {
  	n += 4;
  	x <<= 4;
  }
  if ((x >>> 30) == 0) {
  	n += 2;
  	x <<= 2;
  }
  return n - (x >>> 31);
}


function countTrailing0(x) {
  if (!x) return 32;
  var n = 1;
  if ((x << 16) == 0) n += 16, x >>>= 16;
  if ((x << 24) == 0) n += 8, x >>>= 8;
  if ((x << 28) == 0) n += 4, x >>>= 4;
  if ((x << 30) == 0) n += 2, x >>>= 2;
  return n - (x & 0x01);
}

console.log("leading zero: " + countLeading0(12345));
</script>
</html>